package com.example.socialapp.ui.base.mvi

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.receiveAsFlow
import kotlinx.coroutines.launch

/**
 * Base ViewModel for MVI architecture.
 * Handles the processing of intents, updating state, and emitting side effects.
 *
 * @param State The type of state this ViewModel manages
 * @param Intent The type of intent this ViewModel processes
 * @param Effect The type of side effect this ViewModel emits
 */
abstract class MviViewModel<State : MviState, Intent : MviIntent, Effect : MviEffect> : ViewModel() {

    /**
     * The initial state for the UI
     */
    abstract fun createInitialState(): State

    /**
     * Mutable state flow for UI state
     */
    private val _state = MutableStateFlow(createInitialState())

    /**
     * Public immutable state flow for UI state
     */
    val state: StateFlow<State> = _state

    /**
     * Channel for side effects
     */
    private val _effect = Channel<Effect>(Channel.BUFFERED)

    /**
     * Public flow for side effects
     */
    val effect: Flow<Effect> = _effect.receiveAsFlow()

    /**
     * Process intents from the UI
     *
     * @param intent The intent to process
     */
    abstract fun processIntent(intent: Intent)

    /**
     * Update the current state
     *
     * @param reduce Function that takes the current state and returns a new state
     */
    protected fun updateState(reduce: (State) -> State) {
        val newState = reduce(_state.value)
        _state.value = newState
    }

    /**
     * Emit a side effect
     *
     * @param effect The effect to emit
     */
    protected fun emitEffect(effect: Effect) {
        viewModelScope.launch {
            _effect.send(effect)
        }
    }
} 